package com.usefullc.download.service;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.usefullc.common.exception.BizException;
import com.usefullc.common.util.BeanUtils;
import com.usefullc.common.util.NumberUtil;
import com.usefullc.download.constants.VideoConstants;
import com.usefullc.download.domain.RegisterCode;
import com.usefullc.download.enums.RegisterCodeStatusEnum;
import com.usefullc.download.enums.RegisterCodeTypeEnum;
import com.usefullc.download.mapper.RegisterCodeMapper;
import com.usefullc.download.param.CheckRegisterCodeParam;
import com.usefullc.download.param.RegisterCodeGenParam;
import com.usefullc.download.query.RegisterCodeQuery;
import com.usefullc.download.vo.CheckRegisterCodeVo;
import com.usefullc.system.domain.DataConfig;
import com.usefullc.system.service.AbstractBizService;
import com.usefullc.system.service.DataConfigService;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * @author: Sampson
 * @date: 2022-03-27 15:29
 */
@Service
public class RegisterCodeService extends AbstractBizService<RegisterCodeMapper, RegisterCode, RegisterCodeQuery> {

    @Autowired
    private DataConfigService dataConfigService;

//    @Override
//    public List<Predicate> getPredicates(Root<RegisterCode> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder, BaseQuery q) {
//        RegisterCodeQuery thisQuery = (RegisterCodeQuery) q;
//        List<Predicate> predicates = new ArrayList<>();
//        if (thisQuery.getDelState() != null) {
//            predicates.add(criteriaBuilder.equal(root.get("delState"), thisQuery.getDelState()));
//        }
//        if (thisQuery.getStatus() != null) {
//            predicates.add(criteriaBuilder.equal(root.get("status"), thisQuery.getStatus()));
//        }
//        if (StringUtils.isNotEmpty(thisQuery.getCode())) {
//            predicates.add(criteriaBuilder.equal(root.get("code"), thisQuery.getCode()));
//        }
//        if (StringUtils.isNotEmpty(thisQuery.getMachineId())) {
//            predicates.add(criteriaBuilder.equal(root.get("machineId"), thisQuery.getMachineId()));
//        }
//
//        return predicates;
//    }

    @Override
    protected QueryWrapper<RegisterCode> getQueryWrapper(RegisterCodeQuery query) {
        QueryWrapper<RegisterCode> queryWrapper = super.getQueryWrapper(query);
        return queryWrapper;
    }


    public void genCode(RegisterCodeGenParam param){
        Integer codeNum = param.getCodeNum();
        for (Integer integer = 0; integer < codeNum; integer++) {
            RegisterCode registerCode = new RegisterCode();
            registerCode.setStatus(RegisterCodeStatusEnum.NOT_ACTIVE.getCode());
            registerCode.setCode(UUID.randomUUID().toString());
//            registerCode.setMachineId(param.getMachineId());
            registerCode.setType(RegisterCodeTypeEnum.REGULAR.getCode());
//            DataConfig dataConfig = dataConfigService.findByCode(VideoConstants.PROBATION_DAYS);
//            Integer probationDays = Integer.valueOf(dataConfig.getValue());
            int useMonths = 12;  //12个月
            registerCode.setUseMonths(useMonths);
//            Date date = new Date();
//            registerCode.setGmtActive(date);
//            Date expireDate = DateUtils.addDays(date, param.getDayCount());
//            registerCode.setGmtExpire(expireDate);
            this.save(registerCode);
        }

    }

    @Transactional
    public CheckRegisterCodeVo checkRegisterCode(CheckRegisterCodeParam param) {
        CheckRegisterCodeVo checkRegisterCodeVo = new CheckRegisterCodeVo();
        String machineId = param.getMachineId();

        //根据机器id获取注册码
        RegisterCodeQuery query = new RegisterCodeQuery();
        query.setMachineId(machineId);
        query.setResultLimit(1);
        RegisterCode registerCode = this.findOne(query);
        if (registerCode == null) { //第一次
            registerCode = new RegisterCode();
            registerCode.setStatus(RegisterCodeStatusEnum.ACTIVE.getCode());
            registerCode.setCode(UUID.randomUUID().toString());
            registerCode.setMachineId(param.getMachineId());
            registerCode.setType(RegisterCodeTypeEnum.PROBATION.getCode());
            DataConfig dataConfig = dataConfigService.findByCode(VideoConstants.PROBATION_DAYS);
            Integer probationDays = Integer.valueOf(dataConfig.getValue());
            int useMonths = 1;  //试用一个月
            registerCode.setUseMonths(useMonths);
            Date date = new Date();
            registerCode.setGmtActive(date);
            Date expireDate = DateUtils.addDays(date, probationDays);
            registerCode.setGmtExpire(expireDate);
            this.save(registerCode);

            BeanUtils.beanCopy(registerCode, checkRegisterCodeVo);
        } else {
            query = new RegisterCodeQuery();
            query.setMachineId(machineId);
            query.setStatus(RegisterCodeStatusEnum.ACTIVE.getCode());
            query.setResultLimit(1);
            registerCode = this.findOne(query);
            if (registerCode == null) {
                //获取最近的返回
                query = new RegisterCodeQuery();
                query.setMachineId(machineId);
                query.setResultLimit(1);
                registerCode = this.findOne(query);
            }
            BeanUtils.beanCopy(registerCode, checkRegisterCodeVo);

        }


        //计算过期时间
        Long dayExpire = DateUtil.between( new Date(), checkRegisterCodeVo.getGmtExpire(),DateUnit.DAY, false);
        checkRegisterCodeVo.setDayExpire(dayExpire.intValue());
        return checkRegisterCodeVo;

    }

    @Transactional
    public CheckRegisterCodeVo activeRegisterCode(CheckRegisterCodeParam param) {
        String machineId = param.getMachineId();
        String code = param.getRegisterCode();

        //根据code 获取记录
        RegisterCodeQuery query = new RegisterCodeQuery();
        query.setCode(code);
        query.setResultLimit(1);
        RegisterCode registerCode = this.findOne(query);
        if (registerCode == null) {
            throw new BizException("注册码不合法",false);
        }
        if (registerCode.getStatus() == RegisterCodeStatusEnum.EXPIRED.getCode()) {
            throw new BizException("注册码已过期",false);
        }
        if (StringUtils.isEmpty(registerCode.getMachineId())) {
            //获取已激活的注册码并作废，没有意义，暂时不做多注册码处理
            RegisterCodeQuery thisQuery = new RegisterCodeQuery();
            thisQuery.setMachineId(machineId);
            thisQuery.setStatus(RegisterCodeStatusEnum.ACTIVE.getCode());
            List<RegisterCode> dataList = this.findAll(thisQuery);
            for (RegisterCode entity : dataList) {
                entity.setStatus(RegisterCodeStatusEnum.EXPIRED.getCode());
                this.save(entity);
            }
            //end

            registerCode.setMachineId(machineId);
            registerCode.setStatus(RegisterCodeStatusEnum.ACTIVE.getCode());
            Date date = new Date();
            registerCode.setGmtActive(date);
            Date expireDate = DateUtils.addMonths(date, registerCode.getUseMonths());
            registerCode.setGmtExpire(expireDate);
            this.save(registerCode);
        } else {
            if (!StringUtils.equalsIgnoreCase(machineId,registerCode.getMachineId())) {
                throw new BizException("注册码已占用",false);
            }
        }
        CheckRegisterCodeVo checkRegisterCodeVo = BeanUtils.beanCopy(registerCode, CheckRegisterCodeVo.class);
        //计算过期时间
        Long dayExpire = DateUtil.between( new Date(), checkRegisterCodeVo.getGmtExpire(),DateUnit.DAY, false);
        checkRegisterCodeVo.setDayExpire(dayExpire.intValue());
        return checkRegisterCodeVo;
    }

    /**
     * 推迟试用期(最多7次)
     * @param machineId
     */
    public void delayProbation(String machineId){
        //根据code 获取记录
        RegisterCodeQuery query = new RegisterCodeQuery();
        query.setMachineId(machineId);
        query.setResultLimit(1);
        RegisterCode registerCode = this.findOne(query);
        registerCode.setStatus(RegisterCodeStatusEnum.ACTIVE.getCode());
        Date gmtExpire = DateUtils.addDays(new Date(), 1);
        registerCode.setGmtExpire(gmtExpire);
        Integer delayCount = registerCode.getDelayCount();
        delayCount = NumberUtil.add(delayCount, 1);
        DataConfig dataConfig = dataConfigService.findByCode(VideoConstants.DELAY_MAX_COUNT);
        Integer delayMaxCount = Integer.valueOf(dataConfig.getValue());
        if(delayCount > delayMaxCount){
            throw new BizException("再使用次数超限,请购买注册码",false);
        }
        registerCode.setDelayCount(delayCount);
        this.save(registerCode);
    }


}
